Skip to main content

Webhooks configuration

Our recommendation

We strongly recommend using webhooks to stay updated on important events. By subscribing to our webhook events, you can receive real-time notifications directly to your application, enabling you to act swiftly and efficiently.

Setting Up Webhooks

To start using webhooks, follow these steps:

Facilities Webhooks

  1. Register Your Webhook: Use the Create Facilities Webhook endpoint to create webhooks.

    Request Parameters:

    ParameterTypeDescription
    url requiredstringThe URL endpoint where webhook notifications will be sent
    events requiredstringAn array of event to subscribe to. Refer to the list of Webhook Events for available event types
    facilitiesarrayAn array of facility IDs to limit notifications to specific facilities
    secretsarrayAn array of secret tokens for securing webhook payloads, a maximum of two secrets are allowed, If you do not provide a secret, a random secret will be generated for you
  2. Verify Webhook Signatures: For security, verify the signature of incoming webhook payloads to ensure they are sent from our system.

  3. Handle Events: Implement logic in your application to process the received events and take appropriate actions.

User Webhooks

  1. Register Your Webhook: Use the Create User Webhook endpoint to create webhooks.

    Request Parameters:

    ParameterTypeDescription
    url requiredstringThe URL endpoint where webhook notifications will be sent
    events requiredstringAn array of event to subscribe to. Refer to the list of Webhook Events for available event types
    secretsarrayAn array of secret tokens for securing webhook payloads, a maximum of two secrets are allowed, If you do not provide a secret, a random secret will be generated for you
  2. Verify Webhook Signatures: For security, verify the signature of incoming webhook payloads to ensure they are sent from our system.

  3. Handle Events: Implement logic in your application to process the received events and take appropriate actions.

How to verify the webhook signature:

The header of the request will look like this

```
Nursa-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v1=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
```

Steps to validate the webhook event signature

  1. Get body payload from the incoming event request:

  2. Get the Nursa-Signature header from the incoming event request

  3. Split the header using the , character as the separator to get a list of attributes. Then split each attribute using the = character as the separator to get a prefix and value pair. The value for the prefix t corresponds to the timestamp in seconds, and v1 corresponds to the signature (or signatures if you have more than one secret).

  4. Concatenate the timestamp from the header, the character . and the JSON payload from the body.

  5. Sign the payload with the webhook secret using HMAC with SHA256 hash function, and encode the result with hex.

  6. Compare the signatures

    a. Compare the header's signature (or signatures) to the generated hash. If at least one of them matches, then the signature is correct (that's to guarantee no-downtime rotation).

    b. Calculate the difference between the current and received timestamps, then decide if the difference is within your tolerance.

Code example on how to validate the request

import hmac
import hashlib
from time import time

def main():
# Get request body in JSON format
body = "{\"data\":{\"shiftId\":\"c1099745-10d6-43ec-8c9d-6653d35ffbce\",\"facilityId\":\"f817ca7b-b2bb-4905-a74d-bc2ab403ffa3\",\"clinicianId\":\"1f559150-35a2-452f-98ec-7b9fe27dafbd\",\"at\":\"2023-06-19T20:51:38.372Z\",\"requestedBy\":{\"userId\":\"fb881bf1-f074-4f2c-aa09-422c7a360d2f\",\"email\":\"request@email.com\",\"source\":\"clinician\"}},\"eventType\":\"shift.request.created\"}"
# Get this from request header
signature = "t=1687208610,v1=29421185bad346abe4cbc1ee2048901addd3f9c0a3cff0d4d0022e91dbbdf8d5,v1=6004febfa2e2c5cf3f39e18ff3508ec49c99cad974d9678b6bf1b1a251bb6ca2"
# Must be stored in a safe location
secret = "df5c86cfe88295651cd8adb4e867084bfb08e3f522f4f2b967452871fa1a052a";
validate(body, signature, secret)

def validate(body, signature, secret):
attributes = signature.split(",")
timestamp = resolve_timestamp(attributes)
# 1687208610
payload_to_hash = timestamp + "." + body
hashed = hash_payload(payload_to_hash, secret)
# 29421185bad346abe4cbc1ee2048901addd3f9c0a3cff0d4d0022e91dbbdf8d5

is_valid_signature = len([attr for attr in attributes if attr == "v1=" + hashed]) == 1
is_valid_time = validate_time(timestamp)
print("Is signature valid? " + str(is_valid_signature) + ". Is valid time? " + str(is_valid_time));
return is_valid_signature and is_valid_time

def resolve_timestamp(attributes):
[key] = [attr for attr in attributes if attr.startswith("t=")]
return key.split("=")[1]

def hash_payload(payload, secret):
return hmac.new(bytes(secret, "utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest()

def validate_time(timestamp):
now = int(time())
# You can define how much time you want to consider to prevent replay attacks
five_minutes_in_seconds = 5 * 60
return now < int(timestamp) + five_minutes_in_seconds

main()

Why this helps?

Webhooks provide a mechanism for your system to receive notifications when specific events occur in our system. By utilizing webhooks, you can:

  • Receive instant updates: Get notified immediately when an event happens.
  • Reduce API polling: Minimize the need to frequently check our API for changes.
  • Enhance efficiency: Automate workflows and processes in response to real-time events.

Facilities Webhook Events

EventDescription
shift.createdTriggered when a shift is created.
shift.request.createdTriggered when a shift request is created.
shift.request.cancelledTriggered when a shift request is cancelled.
shift.report.createdTriggered when a shift report is created.
shift.scheduled.cancelledTriggered when a scheduled shift is cancelled.
shift.scheduledTriggered when a shift is scheduled.
shift.report.accepted-automaticallyTriggered when a shift report is automatically accepted.
shift.report.acceptedTriggered when a shift report is accepted.
shift.report.rejectedTriggered when a shift report is rejected.
shift.cancelledTriggered when a shift is cancelled.
allTriggers notifications for all Facilities events.

User Webhook Events

| facility.user-connection.accepted | Triggered when a facility user connection is accepted. | | facility.user-connection.rejected | Triggered when a facility user connection is rejected. | | facility.creation.accepted | Triggered when a facility creation request is accepted. | | facility.creation.rejected | Triggered when a facility creation request is rejected. | | all | Triggers notifications for all User events. |

Please refer to the Webhooks Events page to check the payload of each event.